package com.x.xiaoshuo.ui.read;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.view.View;
import android.view.ViewGroup;

import com.qq.e.ads.nativ.ADSize;
import com.qq.e.ads.nativ.NativeExpressAD;
import com.qq.e.ads.nativ.NativeExpressADView;
import com.qq.e.comm.util.AdError;
import com.x.mvp.base.view.activity.ActivityView;
import com.x.mvp.utils.DensityUtil;
import com.x.xiaoshuo.Constant;
import com.x.xiaoshuo.XApplication;
import com.x.xiaoshuo.manager.SettingManager;
import com.x.xiaoshuo.utils.ScreenUtils;
import com.x.xiaoshuo.utils.XCache;

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.List;

import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import rx.subscriptions.CompositeSubscription;

import static com.x.xiaoshuo.ui.read.ReadAdManager.Callback.TYPE_END;
import static com.x.xiaoshuo.ui.read.ReadAdManager.Callback.TYPE_END_S;
import static com.x.xiaoshuo.ui.read.ReadAdManager.Callback.TYPE_START;


public class ReadAdManager {
    private NativeExpressAD nativeExpressADEnd;
    private NativeExpressAD nativeExpressADEndS;
    private NativeExpressAD nativeExpressADStart;
    private List<NativeExpressADView> nativeExpressADViewEnd;
    private List<NativeExpressADView> nativeExpressADViewEndS;
    private List<NativeExpressADView> nativeExpressADViewStart;

    HashMap<NativeExpressADView, SoftReference<Bitmap>> bitmapHashMap = new HashMap<>();


    NativeExpressADView currentEnd;
    NativeExpressADView currentEndS;
    NativeExpressADView currentStart;


    int marginHeight = DensityUtil.dip2px(XApplication.getInstance(), 15);

    int smallHight = ScreenUtils.getScreenHeight() / 6;
    int normHight = ScreenUtils.getScreenHeight() / 2;
    int startWidth = ScreenUtils.getScreenWidth();
    int startHight = ScreenUtils.getScreenHeight();


    int item = 0;

    final int LOAD_COUNT = 3;

    ActivityView activityView;

    ViewGroup startView;

    ViewGroup endView;

    ViewGroup endViewS;

    protected CompositeSubscription subscriptions = new CompositeSubscription();

    public void addSubscription(Subscription subscription) {
        subscriptions.add(subscription);
    }


    void put(NativeExpressADView view, Bitmap bitmap) {
        SoftReference<Bitmap> bitmapSoftReference = bitmapHashMap.get(view);
        if (bitmapSoftReference != null && bitmapSoftReference.get() != null) {
            return;
        }
        bitmapHashMap.put(view, new SoftReference<Bitmap>(bitmap));
        addSubscription(Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                XCache.get(XApplication.getInstance()).put(view.hashCode() + "", bitmap);
            }
        }).observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io()).subscribe(chapterList -> {

                }, throwable -> {

                }, () -> {

                }));
    }


    Bitmap get(NativeExpressADView view) {
        Bitmap bitmap = null;
        SoftReference<Bitmap> bitmapSoftReference = bitmapHashMap.get(view);
        if (bitmapSoftReference != null) {
            if (bitmapSoftReference.get() != null) {
                bitmap = bitmapSoftReference.get();
            } else {
                bitmap = XCache.get(XApplication.getInstance()).getAsBitmap(view.hashCode() + "");
                put(view, bitmap);
            }
        }
        return bitmap;
    }


    private ADSize getMyADSize() {
        int w = ADSize.FULL_WIDTH;
        int h = ADSize.AUTO_HEIGHT;
        return new ADSize(w, h);
    }

    public ReadAdManager(ActivityView activityView, ViewGroup startView, ViewGroup endView, ViewGroup endSView) {
        this.activityView = activityView;
        if (this.nativeExpressADEnd == null) {
            this.nativeExpressADEnd = new NativeExpressAD(XApplication.getInstance(), getMyADSize()
                    , Constant.ADConstants.APPID, Constant.ADConstants.ChapterEndPosId, new Callback(TYPE_END));
        }

        if (this.nativeExpressADStart == null) {
            this.nativeExpressADStart = new NativeExpressAD(XApplication.getInstance(), getMyADSize()
                    , Constant.ADConstants.APPID, Constant.ADConstants.ChapterStartPosId, new Callback(Callback.TYPE_START));
        }

        if (this.nativeExpressADEndS == null) {
            this.nativeExpressADEndS = new NativeExpressAD(XApplication.getInstance(), getMyADSize()
                    , Constant.ADConstants.APPID, Constant.ADConstants.ChapterEndSPosId, new Callback(Callback.TYPE_END_S));
        }

        this.startView = startView;
        this.endView = endView;
        this.endViewS = endSView;

        int type = SettingManager.getInstance().getScreenOrientation();
        switch (type) {
            case Constant.SCREEN_ORIENTATION_PORTRAIT:
                smallHight = ScreenUtils.getScreenHeight() / 6;
                normHight = ScreenUtils.getScreenHeight() / 2;
                startWidth = ScreenUtils.getScreenWidth();
                startHight = ScreenUtils.getScreenHeight() - marginHeight - ScreenUtils.dpToPxInt(12);
                break;

            case Constant.SCREEN_ORIENTATION_LANDSCAPE:
                smallHight = ScreenUtils.getScreenHeight() / 3;
                normHight = ScreenUtils.getScreenHeight();
                startWidth = ScreenUtils.getScreenWidth();
                startHight = ScreenUtils.getScreenHeight() - marginHeight - ScreenUtils.dpToPxInt(12);
                break;
        }
        load();
    }

    public void load() {
        this.nativeExpressADEnd.loadAD(LOAD_COUNT);
        this.nativeExpressADStart.loadAD(LOAD_COUNT);
        this.nativeExpressADEndS.loadAD(LOAD_COUNT);
    }

    NativeExpressADView getNativeExpressADView(int type) {
        if (TYPE_END == type) {
            return nativeExpressADViewEnd.get(item);
        } else if (TYPE_END_S == type) {
            return nativeExpressADViewEndS.get(item);
        } else {
            return nativeExpressADViewStart.get(item);
        }
    }

    void render() {
        try {
            currentStart = getNativeExpressADView(Callback.TYPE_START);
            currentEnd = getNativeExpressADView(TYPE_END);
            currentEndS = getNativeExpressADView(TYPE_END_S);
        } catch (Exception e) {
            return;
        }
        endView.setVisibility(View.VISIBLE);
        endViewS.setVisibility(View.VISIBLE);
        startView.setVisibility(View.VISIBLE);
        if (startView.getChildCount() > 0) {
            startView.removeAllViews();
        }

        if (endView.getChildCount() > 0) {
            endView.removeAllViews();
        }

        if (endViewS.getChildCount() > 0) {
            endViewS.removeAllViews();
        }

        if (currentStart.getParent() != null) {
            ((ViewGroup) currentStart.getParent()).removeView(currentStart);
        }

        if (currentEnd.getParent() != null) {
            ((ViewGroup) currentEnd.getParent()).removeView(currentEnd);
        }

        if (currentEndS.getParent() != null) {
            ((ViewGroup) currentEndS.getParent()).removeView(currentEndS);
        }

        currentStart.render();
        startView.addView(currentStart);

        currentEnd.render();
        endView.addView(currentEnd);

        currentEndS.render();
        endViewS.addView(currentEndS);

        item++;
        item = item >= LOAD_COUNT ? 0 : item;
        if (item >= LOAD_COUNT) {
            item = 0;
        }
    }

    public Bitmap convertStartBitmap() {
        visibleView(TYPE_START);
        if (currentStart != null) {
            Bitmap screenshot = get(currentStart);
            if (screenshot != null) {
                return screenshot;
            }
            currentStart.setDrawingCacheEnabled(true);
            currentStart.measure(View.MeasureSpec.makeMeasureSpec((int) startWidth, View.MeasureSpec.EXACTLY),
                    View.MeasureSpec.makeMeasureSpec(startHight, View.MeasureSpec.AT_MOST));
            currentStart.layout(0, 0, currentStart.getMeasuredWidth(), currentStart.getMeasuredHeight());
            currentStart.buildDrawingCache();
            currentStart.render();
            if (currentStart.getDrawingCache() == null) {
                currentStart.setDrawingCacheEnabled(false);
                currentStart.destroyDrawingCache();
                return null;
            }
            screenshot = Bitmap.createBitmap(currentStart.getDrawingCache());
            currentStart.setDrawingCacheEnabled(false);
            currentStart.destroyDrawingCache();
            put(currentStart, screenshot);
            return screenshot;
        }
        return null;
    }

    private void marginView(int remain, View view) {
        if (view == null) {
            return;
        }
        ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
        marginLayoutParams.topMargin = ScreenUtils.getScreenHeight() - remain;
        view.setLayoutParams(marginLayoutParams);
    }

    private void visibleView(int type) {
        switch (type) {
            case TYPE_END:
                endView.setVisibility(View.VISIBLE);
                endViewS.setVisibility(View.GONE);
                startView.setVisibility(View.GONE);
                break;
            case TYPE_END_S:
                endView.setVisibility(View.GONE);
                endViewS.setVisibility(View.VISIBLE);
                startView.setVisibility(View.GONE);
                break;
            case TYPE_START:
                endView.setVisibility(View.GONE);
                endViewS.setVisibility(View.GONE);
                startView.setVisibility(View.VISIBLE);
                break;
        }
    }

    public Bitmap convertEndBitmap(int remain) {
        Bitmap ret = null;
        if (remain > normHight) {
            visibleView(TYPE_END);
            ret = convertEndBitmap();
            marginView(remain, endView);
        } else if (remain > smallHight) {
            visibleView(TYPE_END_S);
            ret = convertEndSmallBitmap();
            marginView(remain, endViewS);
        }

        return ret;
    }

    public Bitmap convertEndBitmap() {
        if (currentEnd != null) {
            Bitmap screenshot = get(currentEnd);
            if (screenshot != null) {
                return screenshot;
            }
            currentEnd.setDrawingCacheEnabled(true);
            currentEnd.measure(View.MeasureSpec.makeMeasureSpec((int) ScreenUtils.getScreenWidth(), View.MeasureSpec.EXACTLY),
                    View.MeasureSpec.makeMeasureSpec(normHight, View.MeasureSpec.AT_MOST));
            currentEnd.layout(0, 0, currentEnd.getMeasuredWidth(), currentEnd.getMeasuredHeight());
            currentEnd.buildDrawingCache();
            currentEnd.render();
            if (currentEnd.getDrawingCache() == null) {
                currentEnd.setDrawingCacheEnabled(false);
                currentEnd.destroyDrawingCache();
                return null;
            }
            screenshot = Bitmap.createBitmap(currentEnd.getDrawingCache());
            currentEnd.setDrawingCacheEnabled(false);
            currentEnd.destroyDrawingCache();
            put(currentEnd, screenshot);
            return screenshot;
        }
        return null;
    }

    public Bitmap convertEndSmallBitmap() {
        if (currentEndS != null) {
            Bitmap screenshot = get(currentEndS);
            if (screenshot != null) {
                return screenshot;
            }
            currentEndS.setDrawingCacheEnabled(true);
            currentEndS.measure(View.MeasureSpec.makeMeasureSpec((int) ScreenUtils.getScreenWidth(), View.MeasureSpec.EXACTLY),
                    View.MeasureSpec.makeMeasureSpec(smallHight, View.MeasureSpec.AT_MOST));
            currentEndS.layout(0, 0, currentEndS.getMeasuredWidth(), currentEndS.getMeasuredHeight());
            currentEndS.buildDrawingCache();
            currentEndS.render();
            if (currentEndS.getDrawingCache() == null) {
                currentEndS.setDrawingCacheEnabled(false);
                currentEndS.destroyDrawingCache();
                return null;
            }
            screenshot = Bitmap.createBitmap(currentEndS.getDrawingCache());
            currentEndS.setDrawingCacheEnabled(false);
            currentEndS.destroyDrawingCache();
            put(currentEndS, screenshot);
            return screenshot;
        }
        return null;
    }


    public Bitmap convertStartBitmapInner() {
        if (currentStart != null) {
            Bitmap screenshot;
            screenshot = Bitmap.createBitmap(currentStart.getWidth(), currentStart.getHeight(), Bitmap.Config.RGB_565);
            Canvas c = new Canvas(screenshot);
            currentStart.draw(c);
            return screenshot;
        }
        return null;
    }


    public Bitmap convertEndBitmapInner() {
        if (currentEnd != null) {
            Bitmap screenshot;
            screenshot = Bitmap.createBitmap(currentEnd.getWidth(), currentEnd.getHeight(), Bitmap.Config.RGB_565);
            Canvas c = new Canvas(screenshot);
            currentEnd.draw(c);
            return screenshot;
        }
        return null;
    }

    public Bitmap convertEndSmallBitmapInner() {
        if (currentEndS != null) {
            Bitmap screenshot;
            screenshot = Bitmap.createBitmap(currentEndS.getWidth(), currentEndS.getHeight(), Bitmap.Config.RGB_565);
            Canvas c = new Canvas(screenshot);
            currentEndS.draw(c);
            return screenshot;
        }
        return null;
    }

    public void click(int type) {
    }


    private void destroyAdViewLst(List<NativeExpressADView> list) {
        if (list != null) {
            for (NativeExpressADView nativeExpressADView : list) {
                nativeExpressADView.destroy();
            }
        }
    }

    public void destroyAdView() {
        if (startView.getChildCount() > 0) {
            startView.removeAllViews();
        }

        if (endView.getChildCount() > 0) {
            endView.removeAllViews();
        }

        if (endViewS.getChildCount() > 0) {
            endViewS.removeAllViews();
        }
        destroyAdViewLst(nativeExpressADViewEnd);
        destroyAdViewLst(nativeExpressADViewEndS);
        destroyAdViewLst(nativeExpressADViewStart);
        for (SoftReference<Bitmap> bitmapSoftReference : bitmapHashMap.values()) {
            Bitmap bitmap = bitmapSoftReference.get();
            if (bitmap != null) {
                if (!bitmap.isRecycled()) {
                    bitmap.recycle();
                    System.gc();
                }
            }
            bitmapSoftReference.clear();
        }

        for (NativeExpressADView nativeExpressADView : bitmapHashMap.keySet()) {
            XCache.get(XApplication.getInstance()).remove(nativeExpressADView.hashCode() + "");
        }

        subscriptions.unsubscribe();

    }

    class Callback implements NativeExpressAD.NativeExpressADListener {
        public static final int TYPE_END = 0;
        public static final int TYPE_END_S = 3;
        public static final int TYPE_START = 1;
        int type;

        public Callback(int type) {
            this.type = type;
        }

        @Override
        public void onNoAD(AdError adError) {

        }

        @Override
        public void onADLoaded(List<NativeExpressADView> list) {
            if (type == TYPE_END) {
                nativeExpressADViewEnd = list;
            } else if (type == TYPE_END_S) {
                nativeExpressADViewEndS = list;
            } else {
                nativeExpressADViewStart = list;
            }
            if (nativeExpressADViewEnd != null && nativeExpressADViewStart != null && nativeExpressADViewEndS != null) {
                render();
            }
        }

        @Override
        public void onRenderFail(NativeExpressADView nativeExpressADView) {

        }

        @Override
        public void onRenderSuccess(NativeExpressADView nativeExpressADView) {

        }

        @Override
        public void onADExposure(NativeExpressADView nativeExpressADView) {

        }

        @Override
        public void onADClicked(NativeExpressADView nativeExpressADView) {

        }

        @Override
        public void onADClosed(NativeExpressADView nativeExpressADView) {

        }

        @Override
        public void onADLeftApplication(NativeExpressADView nativeExpressADView) {

        }

        @Override
        public void onADOpenOverlay(NativeExpressADView nativeExpressADView) {

        }

        @Override
        public void onADCloseOverlay(NativeExpressADView nativeExpressADView) {

        }
    }
}
